package com.hlkj.baojin.service.impl;


import com.hlkj.baojin.dao.ILocalOssDao;
import com.hlkj.baojin.entity.LocalOss;
import com.hlkj.baojin.service.IFileService;
import com.hlkj.baojin.utils.ErrororUtil;
import com.hlkj.baojin.utils.bean.IdGenerator;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static java.time.Instant.now;

@Service
public class FileServiceImpl implements IFileService {
    @Value("${oos.path}")
    private String OOS_PATH;
    @Value("${oos.savePath}")
    private String SAVE_PATH;
    @Value("${myserver.use}")
    private Boolean serverUse;
    @Value("${myserver.ip}")
    private String serverIp;
    @Value("${myserver.port}")
    private String serverPort;

    @Autowired
    private ILocalOssDao localOssDao;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());


    @Override
    @Transactional
    public String saveFileLocalhost(MultipartFile multipartFile) {
        Instant now = now();
        if (multipartFile == null || multipartFile.isEmpty()) {
            ErrororUtil.runThrow(null, "资源管理", "文件为空");
        }
        // 获取文件名
        String fileName = multipartFile.getOriginalFilename();
        // 获取文件的后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        //将Date对象转化为yyyy-MM-dd形式的字符串
        String mMdd = new SimpleDateFormat("yyyyMMdd").format(new Date());
        // 文件上传后的路径
        StringBuffer filePath;
        if (testWindows()) {
            filePath = new StringBuffer("E:" + File.separator + "bjjkoos" + File.separator + mMdd + File.separator);
        } else {
            filePath = new StringBuffer(SAVE_PATH + File.separator + "bjjkoos" + File.separator + mMdd + File.separator);
        }
        LocalOss localOss = new LocalOss();
        // 解决中文问题，liunx下中文路径，图片显示问题
//        fileName = IdGenerator.getUUID() + suffixName;
        localOss.setFileName(fileName);
        localOss.setCreateTime(System.currentTimeMillis());
        boolean isImg = false;
        switch (suffixName.substring(1)) {
            case "mp4":
                localOss.setType(1);
                filePath.append("video").append(File.separator).append(IdGenerator.getUUID()).append(File.separator);
                break;
            case "jpg":
            case "png":
            case "JPG":
                isImg = true;
                localOss.setType(0);
                filePath = new StringBuffer(filePath.toString().replaceAll("bjjkoos", "bjjkoosB"))
                        .append("img").append(File.separator).append(IdGenerator.getUUID()).append(File.separator);
//                localOss.setPath(filePath.append(fileName).toString());
                localOss.setPath(filePath.substring(filePath.indexOf("bjjkoosB") +9) + fileName);
                localOss.setCatalog(filePath.substring(filePath.indexOf("bjjkoosB") + 9));
                break;
            case "doc":
            case "docx":
            case "xls":
            case "xlsx":
            case "txt":
            case "pdf":
                localOss.setType(2);
                filePath.append("office").append(File.separator).append(IdGenerator.getUUID()).append(File.separator);
                break;
            default:
                filePath.append("other").append(File.separator).append(IdGenerator.getUUID()).append(File.separator);
                break;
        }
        if (!isImg) {
            localOss.setPath(filePath.substring(filePath.indexOf("bjjkoos") + 8) + fileName);
            localOss.setCatalog(filePath.substring(filePath.indexOf("bjjkoos") + 8));
        }
        File dest = new File(filePath + fileName);

        // 检测是否存在目录
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            logger.info("文件本地实例化开始：++耗时：" + Duration.between(now, now()).toMillis());
            now = now();
            file1(multipartFile, dest);
            logger.info("文件本地保存结束：++耗时：" + Duration.between(now, now()).toMillis());
            now = now();
            //            同步到ftp
//            ftp服务保存地址
//            上传到ftp的文件名
//            lename 待上传文件的名称（绝对地址）
//            InputStream inputStream = multipartFile.getInputStream();
//            file3(filePath, fileName, 1);
            if (isImg) {
                String s = (filePath + fileName).replaceAll("bjjkoosB", "bjjkoos");
                File img = new File(s);
                if (!img.getParentFile().exists()) {
                    img.getParentFile().mkdirs();
                }
                file2(filePath, fileName, img);
            }

            localOss = localOssDao.save(localOss);
            return localOss.getId();
        } catch (IllegalStateException | IOException e) {
            e.printStackTrace();
        }
        throw new IllegalArgumentException("上传失败");
    }


    @Async
    void file1(MultipartFile multipartFile, File dest) throws IOException {
        multipartFile.transferTo(dest);
    }
    void file2(StringBuffer filePath, String fileName, File img) throws IOException {
        Thumbnails.of(filePath + fileName)
                .scale(1f)
                .outputQuality(0.2f)
                .toFile(img);
    }

    @Override
    public List<String> getFileLocalhost(List<String> id) {
        if (id == null) {
            return null;
        }
        List<LocalOss> byId = localOssDao.findByIdIn(id.toArray());
        List<String> collect = byId.stream().map(localOss -> {
            //检测操作系统
            if (testWindows()) {
                InetAddress localHost = null;
                try {
                    localHost = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                assert localHost != null;
                if(serverUse) {
                    return "http://" + serverIp + ":" + serverPort + "/bjjkoos/" + File.separator + localOss.getPath();
                }else {
                    return "http://" + localHost.getHostAddress() + "/bjjkoos/" + File.separator + localOss.getPath();
                }
            } else {
                return OOS_PATH + "/bjjkoos/" + localOss.getPath();
            }
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    public String getFileLocalhost(String id) {
        if (id == null) {
            return null;
        }
        Optional<LocalOss> byId = localOssDao.findById(id);
        if (byId.isPresent()) {
            //检测操作系统
            if (testWindows()) {
                InetAddress localHost = null;
                try {
                    localHost = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                assert localHost != null;
                if(serverUse) {
                    return "http://" + serverIp + ":" + serverPort + "/bjjkoos/" + File.separator + byId.get().getPath();
                }else {
                    return "http://" + localHost.getHostAddress() + "/bjjkoos/" + File.separator + byId.get().getPath();
                }
            } else {
                return OOS_PATH + "/bjjkoos/" + byId.get().getPath();
            }
        }
        return null;
    }

    @Override
    public String getBigImg(String id) {
        if (id == null) {
            return null;
        }
        Optional<LocalOss> byId = localOssDao.findById(id);
        if (byId.isPresent()) {
            //检测操作系统
            if (testWindows()) {
                InetAddress localHost = null;
                try {
                    localHost = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                assert localHost != null;
                if(serverUse) {
                    return "http://" + serverIp + ":" + serverPort + "/bjjkoosB/" + File.separator + byId.get().getPath();
                }else {
                    return "http://" + localHost.getHostAddress() + "/bjjkoosB/" + File.separator + byId.get().getPath();
                }
            } else {
                return OOS_PATH + "/bjjkoosB/" + byId.get().getPath();
            }
        }
//        String localIP = IpUtil.getLocalIP();
//        if(byId.isPresent()){
//            return "http://"+localIP+"/bjjkoosB/"+byId.get().getPath();
//        }
        return null;
    }

    private boolean testWindows() {
        return System.getProperties().getProperty("os.name").toUpperCase().contains("WINDOWS");
    }

    @Override
    public List<String> updateMultiFile(List<String> fileNames) {

        List<String> stringResult = new ArrayList<>();
        for (String fileName : fileNames) {
            if (fileName.contains("http")) {
                LocalOss localOss = localOssDao.findByPathLike(fileName.substring(fileName.lastIndexOf("/\\") + 2));
                stringResult.add(localOss.getId());
            } else {
                stringResult.add(fileName);
            }
        }
        return stringResult;
    }

    @Override
    public List<String> transform(List<String> paths) {
        List<String> pathsResult = new ArrayList<>();
        paths.forEach(path -> {
            pathsResult.add(getFileLocalhost(path));
        });
        return pathsResult;
    }
}